package com.ruoyi.common.utils;

import io.netty.buffer.ByteBuf;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MyByteUtil {


    public static void logByteBuf(ByteBuf buffer) {
        int length = buffer.readableBytes();
        int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
        StringBuilder buf = new StringBuilder(rows * 80 * 2)
                .append("read index:").append(buffer.readerIndex())
                .append(" write index:").append(buffer.writerIndex())
                .append(" capacity:").append(buffer.capacity())
                .append(StringUtil.NEWLINE);
        io.netty.buffer.ByteBufUtil.appendPrettyHexDump(buf, buffer);
        System.out.println(buf.toString());
    }

    /**
     * 从一个字节中获取指定位的值。index从高位(即左边)开始递增。getBitValueFromByte(srcByte, 0)表示从左往右取字节srcByte的第1位的值。
     *
     * @param srcByte
     * @param index
     * @return
     * @throws IllegalArgumentException
     */
    public static byte getBitValueFromByte(byte srcByte, int index) throws IllegalArgumentException {
        return getBitValueFromByte(srcByte, index, index);
    }

    /**
     * 从一个字节中获取指定位的值。
     * 注意：此方法是从高位往低位取值，即从左往右。beginIndex表示高位的起始位，endIndex表示低位的结束位。
     * 示例：getBitValueFromByte(srcByte, 0, 2)表示从左往右取字节srcByte的第1位(含)至第3位(含)，共3位。
     *
     * @param srcByte
     * @param beginIndex 起始位索引(包含)
     * @param endIndex   结束位索引(包含)
     * @return
     * @throws IllegalArgumentException
     */
    public static byte getBitValueFromByte(byte srcByte, int beginIndex, int endIndex) throws IllegalArgumentException {
        if (beginIndex < 0 || beginIndex >= 8 || endIndex < 0 || endIndex >= 8 || beginIndex > endIndex) {
            throw new IllegalArgumentException("参数错误, beginIndex,endIndex均必须大于或等于0，小于8，且beginIndex必须小于或等于endIndex.");
        }

        if (beginIndex == endIndex) {
            return Byte.parseByte(String.valueOf(byteToBinStr(srcByte).charAt(beginIndex)), 2);
        } else {
            return Byte.parseByte(byteToBinStr(srcByte).substring(beginIndex, endIndex + 1), 2);
        }
    }

    /**
     * 从一个int数值中获取指定位的值。
     *
     * @param srcIntValue
     * @param index
     * @return
     */
    public static int getBitValueFromInt(int srcIntValue, int index) {
        return getBitValueFromInt(srcIntValue, index, index);
    }

    /**
     * 从一个int数值中获取指定范围内位的值。
     * 注意：
     * 1,此方法是从低位往高位取值，即从右往左。
     *
     * @param srcIntValue
     * @param beginIndex  起始位索引(包含)，低位(右边)。
     * @param endIndex    结束位索引(包含)，从高位(左边)。
     * @return
     * @throws IllegalArgumentException
     */
    public static int getBitValueFromInt(int srcIntValue, int beginIndex, int endIndex) throws IllegalArgumentException {
        if (beginIndex < 0 || endIndex < 0 || endIndex >= 31 || beginIndex > endIndex) {
            throw new IllegalArgumentException("参数错误, beginIndex,endIndex均必须大于等于0，且小于8.");
        }

        return Integer.parseInt(intToBinStr(srcIntValue).substring(31 - endIndex, 31 - beginIndex + 1), 2);
    }

    /**
     * 把单个字节转换成二进制字符串。参考博文：https://blog.csdn.net/guishuanglin/article/details/103418907
     */
    public static String byteToBinStr(byte b) {
        String zero = "00000000";
        String binStr = Integer.toBinaryString(b & 0xFF);
        if (binStr.length() < 8) {
            binStr = zero.substring(0, 8 - binStr.length()) + binStr;
        }
        return binStr;
    }

    /**
     * 将int值转为二进制字符串。如：1000转为 "00000000000000000000001111101000"。
     *
     * @param b
     * @return
     */
    public static String intToBinStr(int b) {
        String zero = "00000000000000000000000000000000";
        String binStr = Integer.toBinaryString(b); //结果："1111101000"
        if (binStr.length() < 32) {
            binStr = zero.substring(0, 32 - binStr.length()) + binStr;
        }
//        log.info("binStr: {}", binStr); //结果："00000000000000000000001111101000"
        return binStr;
    }

    /**
     * 将int值写入目标int值中的指定位。
     *
     * @param srcValue
     * @param dstValue
     * @param index
     * @return
     */
    public static int writeValueToAssignBit(int srcValue, int dstValue, int index) {
        return writeValueToAssignBit(srcValue, dstValue, index, index);
    }

    /**
     * 将int值写入目标int值中的指定范围的位。
     *
     * @param srcValue
     * @param dstValue
     * @param beginIndex
     * @param endIndex
     * @return
     */
    public static int writeValueToAssignBit(int srcValue, int dstValue, int beginIndex, int endIndex) {
        if (beginIndex > endIndex) throw new IllegalArgumentException("beginIndex不能大于endIndex");

        int length = endIndex - beginIndex + 1;
        String srcBinStr = intToBinStr(srcValue);
        StringBuilder dstBinStr = new StringBuilder(intToBinStr(dstValue));

        int dstBeginIndex = 31 - endIndex;
        for (int i = 0; i < length; i++) {
            dstBinStr.setCharAt(dstBeginIndex + i, srcBinStr.charAt(31 - length + 1 + i));
        }

//        log.info("dstBinStr: {}", dstBinStr);

        int parseInt = Integer.parseInt(dstBinStr.toString(), 2);
//        log.info("parseInt: {}", parseInt);

        return parseInt;
    }
}
